package com.wei.czz.framework.common.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.huaweicloud.sdk.smsapi.v1.SMSApiClient;
import com.huaweicloud.sdk.smsapi.v1.model.BatchSendSmsRequest;
import com.huaweicloud.sdk.smsapi.v1.model.BatchSendSmsRequestBody;
import com.huaweicloud.sdk.smsapi.v1.model.BatchSendSmsResponse;
import com.wei.czz.common.dto.common.NameValue;
import com.wei.czz.common.dto.common.sms.SendSmsDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.sms.SmsChannelEnum;
import com.wei.czz.common.enums.common.sms.SmsTypeEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.property.SmsProperty;
import com.wei.czz.framework.common.entity.SmsTemplateEntity;
import com.wei.czz.framework.common.helper.SmsSendHelper;
import com.wei.czz.framework.common.service.SmsService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2025-01-15 15:49:38
 * className: HwSmsServiceImpl
 * version: 1.0
 * description:
 */
@Service("hwSmsService")
@AllArgsConstructor
public class HwSmsServiceImpl implements SmsService {

    private static final Logger log = LoggerFactory.getLogger(HwSmsServiceImpl.class);

    /**
     * 通道号
     */
    private static final String FORM = "form";

    /**
     * 模板ID
     */
    private static final String TEMPLATE = "template";

    private SmsProperty smsProperty;

    private SMSApiClient huaweiSmsClient;

    @PostConstruct
    public void init() {
        SmsSendHelper.register(SmsChannelEnum.HW.getValue(), this);
    }

    /**
     * 发送短信操作
     *
     * @param mobile      接收手机号
     * @param smsTemplate 短信模板对象
     * @param paramMap    短信参数映射
     * @return 发送结果
     */
    @Override
    public SendSmsDto sendSms(String mobile, SmsTemplateEntity smsTemplate, Map<String, String> paramMap) {
        log.info("开始华为云短信发送操作。mobile={} type={} code={} paramMap={}", mobile,
                SmsTypeEnum.getName(smsTemplate.getType()), smsTemplate.getCode(), paramMap);
        if (Boolean.FALSE.equals(smsProperty.getOpen())) {
            log.warn("未开启华为云短信发送，请确认");
            SendSmsDto sendSmsDto = new SendSmsDto();
            sendSmsDto.setStatus(CommonEnum.ZERO.getValue());
            return sendSmsDto;
        }

        /*
            获取渠道参数映射
         */
        Map<String, NameValue<String>> channelParamMap = this.getChannelParam(smsTemplate.getChannelParam());
        NameValue<String> form = channelParamMap.get(FORM);
        NameValue<String> template = channelParamMap.get(TEMPLATE);
        if (ObjectUtils.anyNull(form, template)) {
            log.info("华为云短信模板参数不存在");
            throw new CzzException("华为云短信模板配置有误，发送失败");
        }

        SmsProperty.HuaweiSmsProperty property = smsProperty.getHw();

        List<String> paramList = new ArrayList<>();
        for (String param : smsTemplate.getParams().split(",")) {
            paramList.add(paramMap.get(param));
        }

        BatchSendSmsRequestBody requestBody = new BatchSendSmsRequestBody()
                .withFrom(form.getValue())
                .withTo(mobile)
                .withTemplateId(template.getValue())
                .withTemplateParas(JSON.toJSONString(paramList))
                .withStatusCallback(property.getCallbackUrl());
        BatchSendSmsRequest request = new BatchSendSmsRequest();
        request.setBody(requestBody);

        SendSmsDto sendSmsDto = new SendSmsDto();
        sendSmsDto.setStatus(CommonEnum.ZERO.getValue());
        try {
            /*
                发送短信
             */
            BatchSendSmsResponse response = huaweiSmsClient.batchSendSms(request);
            log.info("华为云短信发送完成 {}", response);
            if (!Objects.equals("200", response.getCode())) {
                sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                        .setMsg(response.getDescription());
                return sendSmsDto;
            }

            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("result", JSON.toJSONString(response.getResult()));

            sendSmsDto.setResultMap(resultMap);
        } catch (Exception e) {
            log.info("华为云短息发送异常。message={}", e.getMessage(), e);
            sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                    .setMsg("华为云短息发送失败");
        }
        log.info("华为云短信发送操作结束");
        return sendSmsDto;
    }

    /**
     * 批量发送短信操作
     *
     * @param mobileList  接收手机号列表
     * @param smsTemplate 短信模板对象
     * @param paramMap    短信参数映射
     * @return 发送结果
     */
    @Override
    public SendSmsDto batchSendSms(List<String> mobileList, SmsTemplateEntity smsTemplate, Map<String, String> paramMap) {
        log.info("开始华为云短信批量发送操作。mobileList={} type={} code={} paramMap={}", mobileList,
                SmsTypeEnum.getName(smsTemplate.getType()), smsTemplate.getCode(), paramMap);
        if (Boolean.FALSE.equals(smsProperty.getOpen())) {
            log.warn("未开启华为云短信发送，请确认");
            SendSmsDto sendSmsDto = new SendSmsDto();
            sendSmsDto.setStatus(CommonEnum.ZERO.getValue());
            return sendSmsDto;
        }

        /*
            获取渠道参数映射
         */
        Map<String, NameValue<String>> channelParamMap = this.getChannelParam(smsTemplate.getChannelParam());
        NameValue<String> form = channelParamMap.get(FORM);
        NameValue<String> template = channelParamMap.get(TEMPLATE);
        if (ObjectUtils.anyNull(form, template)) {
            log.info("华为云短信模板参数不存在");
            throw new CzzException("华为云短信模板配置有误，发送失败");
        }

        SmsProperty.HuaweiSmsProperty property = smsProperty.getHw();

        List<String> paramList = new ArrayList<>();
        for (String param : smsTemplate.getParams().split(",")) {
            paramList.add(paramMap.get(param));
        }

        BatchSendSmsRequestBody requestBody = new BatchSendSmsRequestBody()
                .withFrom(form.getValue())
                .withTo(String.join(",", mobileList))
                .withTemplateId(template.getValue())
                .withTemplateParas(JSON.toJSONString(paramList))
                .withStatusCallback(property.getCallbackUrl());
        BatchSendSmsRequest request = new BatchSendSmsRequest();
        request.setBody(requestBody);

        SendSmsDto sendSmsDto = new SendSmsDto();
        sendSmsDto.setStatus(CommonEnum.ZERO.getValue());
        try {
            /*
                发送短信
             */
            BatchSendSmsResponse response = huaweiSmsClient.batchSendSms(request);
            log.info("华为云短信批量发送完成 {}", response);
            if (!Objects.equals("200", response.getCode())) {
                sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                        .setMsg(response.getDescription());
                return sendSmsDto;
            }

            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("result", JSON.toJSONString(response.getResult()));

            sendSmsDto.setResultMap(resultMap);
        } catch (Exception e) {
            log.info("华为云短息批量发送异常。message={}", e.getMessage(), e);
            sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                    .setMsg("华为云短息发送失败");
        }
        log.info("华为云短信批量发送操作结束");
        return sendSmsDto;
    }

    /**
     * 获取短信渠道自有参数操作
     *
     * @return 短信参数映射
     */
    @Override
    public Map<String, NameValue<String>> getChannelParam(String channelParam) {
        Map<String, NameValue<String>> paramMap = Optional.ofNullable(channelParam)
                .filter(StringUtils::isNotBlank)
                .map(param -> JSON.parseObject(param, new TypeReference<Map<String, NameValue<String>>>() {}))
                .orElse(Collections.emptyMap());

        Map<String, NameValue<String>> channelParamMap = new LinkedHashMap<>();
        channelParamMap.put(FORM, paramMap.getOrDefault(FORM, new NameValue<>("通道号", StringUtils.EMPTY)));
        channelParamMap.put(TEMPLATE, paramMap.getOrDefault(TEMPLATE, new NameValue<>("模板ID", StringUtils.EMPTY)));
        return channelParamMap;
    }

}
